/*!
\copyright  Copyright (c) 2020-2024 Qualcomm Technologies International, Ltd.
            All Rights Reserved.
            Qualcomm Technologies International, Ltd. Confidential and Proprietary.
\file
\defgroup   le_audio_messages_domain LE Audio Messages
\ingroup    bt_domain
\brief      Functions for generating LE Audio notification messages.
*/

#ifndef LE_AUDIO_MESSAGES_H_
#define LE_AUDIO_MESSAGES_H_

#include <message.h>

#include "audio_sources.h"
#include "domain_message.h"
#include "multidevice.h"
#include "bt_types.h"
#include <bdaddr.h>

/*! @{ */

/*! Invalid Isochronous handle value. */
#define LE_AUDIO_INVALID_ISO_HANDLE         ((uint16) 0xFFFF)

/*! CIS direction. */
#define LE_AUDIO_ISO_DIRECTION_DL           ((uint8) (1u << 0u))      /* Phone to Headset */
#define LE_AUDIO_ISO_DIRECTION_UL           ((uint8) (1u << 1u))      /* Headset to phone */
#define LE_AUDIO_ISO_DIRECTION_BOTH         ((uint8) (LE_AUDIO_ISO_DIRECTION_DL | LE_AUDIO_ISO_DIRECTION_UL))

/*! Messages sent by the LE Audio domain to interested clients. */
enum le_audio_domain_messages
{
    /*! message to inform a LE broadcast audio source is connected */
    LE_AUDIO_BROADCAST_CONNECTED = LE_AUDIO_MESSAGE_BASE,

    /*! message to inform a LE broadcast audio source is disconnected */
    LE_AUDIO_BROADCAST_DISCONNECTED,

    /*! message to send broadcast metadata extracted from PA train */
    LE_AUDIO_BROADCAST_METADATA_PAYLOAD,

    /*! LE audio unicast enable recieved from AG. Application can cache this information for setting selective
        available audio context */
    LE_AUDIO_UNICAST_ENABLED,

    /*! message to inform a CIS for LE Unicast audio got connected */
    LE_AUDIO_UNICAST_CIS_CONNECTED,

    /*! message to inform a CIS for LE Unicast audio got disconnected */
    LE_AUDIO_UNICAST_CIS_DISCONNECTED,

    /*! message to inform a LE Unicast voice source is connected */
    LE_AUDIO_UNICAST_VOICE_CONNECTED,

    /*! message to inform a LE Unicast voice source is disconnected */
    LE_AUDIO_UNICAST_VOICE_DISCONNECTED,

    /*! message to inform a LE Unicast audio source has started streaming */
    LE_AUDIO_UNICAST_MEDIA_CONNECTED,

    /*! message to inform a LE Unicast audio source has stopped streaming */
    LE_AUDIO_UNICAST_MEDIA_DISCONNECTED,

    /*! message to inform a LE Unicast audio source has established data path for CISes */
    LE_AUDIO_UNICAST_MEDIA_DATA_PATH_READY,

    /*! message to inform a LE Unicast audio source stream has been disabled from AG. Application can cache this
        information for setting selective available audio context */
    LE_AUDIO_UNICAST_DISABLED_IND,

    /*! message to inform a LE Unicast audio source has updated metadata. Application can cache this information for
        setting selective available audio context */
    LE_AUDIO_UNICAST_UPDATE_METADATA_IND,

    /*! message to inform a LE Unicast audio source has been updated.*/
    LE_AUDIO_UNICAST_MEDIA_UPDATE_IND,
};

/*! Message body for \ref LE_AUDIO_UNICAST_CONNECTED. */
typedef struct
{
    /*! Connected audio source. */
    audio_source_t      audio_source;
} LE_AUDIO_BROADCAST_CONNECTED_T;

typedef LE_AUDIO_BROADCAST_CONNECTED_T LE_AUDIO_BROADCAST_DISCONNECTED_T;

/*! Message body for \ref LE_AUDIO_BROADCAST_METADATA_PAYLOAD. */
typedef struct
{
    /*! Length of metadata */
    uint8 metadata_len;
    /*! Metadata Payload */
    uint8 metadata[1];
} LE_AUDIO_BROADCAST_METADATA_PAYLOAD_T;

/*! Message body for \ref LE_AUDIO_UNICAST_ENABLED. */
typedef struct
{
    /*! Indicates the connection id */
    gatt_cid_t  cid;

    /*! Indicates enable is for which side */
    multidevice_side_t  side;

    /*! Does the enabled unicast has foreground status? */
    bool is_foreground;

    /*! Connected audio source. */
    generic_source_t            audio_source;

    /*! Streaming context used by connected device */
    uint16                      streaming_audio_context;
} LE_AUDIO_UNICAST_ENABLED_T;

/*! Message body for \ref LE_AUDIO_UNICAST_CIS_CONNECTED. */
typedef struct
{
    /*! Indicates connect is for which side */
    multidevice_side_t  side;
    /*! CIS identifier for the connected isochronous stream */
    uint8               cis_id;
    /*! CIS direction */
    uint8               cis_dir;
    /*! CIS handle for the connected isochronous stream */
    uint16              cis_handle;
    /*! GATT Connection Id */
    gatt_cid_t cid;
} LE_AUDIO_UNICAST_CIS_CONNECTED_T;

/*! Message body for \ref LE_AUDIO_UNICAST_CIS_DISCONNECTED. */
typedef LE_AUDIO_UNICAST_CIS_CONNECTED_T LE_AUDIO_UNICAST_CIS_DISCONNECTED_T;

/*! Message body for \ref LE_AUDIO_UNICAST_MEDIA_CONNECTED. */
typedef struct
{
    /*! Connected audio source. */
    audio_source_t      audio_source;

    /*! Connected audio context. */
    uint16              audio_context;
} LE_AUDIO_UNICAST_MEDIA_CONNECTED_T;

/*! Message body for \ref LE_AUDIO_UNICAST_MEDIA_DISCONNECTED. */
typedef LE_AUDIO_UNICAST_MEDIA_CONNECTED_T LE_AUDIO_UNICAST_MEDIA_DISCONNECTED_T;

/*! Message body for \ref LE_AUDIO_UNICAST_VOICE_CONNECTED. */
typedef struct
{
    /*! Connected audio source. */
    voice_source_t      voice_source;
} LE_AUDIO_UNICAST_VOICE_CONNECTED_T;

/*! Message body for \ref LE_AUDIO_UNICAST_VOICE_DISCONNECTED. */
typedef LE_AUDIO_UNICAST_VOICE_CONNECTED_T LE_AUDIO_UNICAST_VOICE_DISCONNECTED_T;

/*! Message body for \ref LE_AUDIO_UNICAST_DISABLED_IND */
typedef struct
{
    /*! Connected handset */
    gatt_cid_t                  cid;

    /*! Connected/disconnected audio source. */
    generic_source_t            audio_source;

    /*! Streaming context used by connected device */
    uint16                      streaming_audio_context;
} LE_AUDIO_UNICAST_DISABLED_IND_T;

/*! Message body for \ref LE_AUDIO_UNICAST_UPDATE_METADATA_IND */
typedef LE_AUDIO_UNICAST_DISABLED_IND_T LE_AUDIO_UNICAST_UPDATE_METADATA_IND_T;

/*! Message body for \ref LE_AUDIO_UNICAST_MEDIA_UPDATE_IND */
typedef struct
{
    /*! Connected/disconnected audio source. */
    audio_source_t            audio_source;
} LE_AUDIO_UNICAST_MEDIA_UPDATE_IND_T;

/*! \brief Setup the LE Audio message delivery framework.

    \param init_task Not used.

    \return TRUE
 */
#if (defined(INCLUDE_LE_AUDIO_UNICAST) || defined(INCLUDE_LE_AUDIO_BROADCAST))
bool LeAudioMessages_Init(Task init_task);
#else
#define LeAudioMessages_Init(init_task) (FALSE)
#endif

#if (defined(INCLUDE_LE_AUDIO_UNICAST) || defined(INCLUDE_LE_AUDIO_BROADCAST))
/*! \brief Register task to receive LE Audio messages.

    \param task_to_register
 */
void LeAudioMessages_ClientRegister(Task task_to_register);

/*! \brief Deregister task that registered to receive LE Audio messages.

    \param task_to_deregister
 */
void LeAudioMessages_ClientDeregister(Task task_to_deregister);
#else
#define LeAudioMessages_ClientRegister(task_to_register) ((void) (0))
#endif

#ifdef INCLUDE_LE_AUDIO_BROADCAST
/*! \brief Send an LE Audio broadcast connect/disconnect message.

    \param id           The notification message id
    \param audio_source Audio source identifier.
 */
void LeAudioMessages_SendBroadcastConnectStatus(MessageId id, audio_source_t audio_source);

/*! \brief Send broadcast metadata extracted from PA train to registered clients.

    \param metadata_len metadata length
    \param metadata Pointer to broadcast metadata.
 */
void LeAudioMessages_SendBroadcastMetadata(uint8 metadata_len, uint8 *metadata);
#else
#define LeAudioMessages_SendBroadcastConnectStatus(id, audio_source) ((void) (0))
#define LeAudioMessages_SendBroadcastMetadata(metadata_len, metadata) ((void) (0))
#endif

#ifdef INCLUDE_LE_AUDIO_UNICAST

/*! \brief Send an Remote LE Audio unicast enabled notification message.

    \param cid           The connection id of the device for which the Unicast enabled has to be sent
    \param side          Side for which unicast config data is available.
    \param audio_context The streaming audio context
    \param source        The generic source associated with the unicast enable.
    \param is_foreground Is the unicast session foreground
 */
void LeAudioMessages_SendUnicastEnabled(gatt_cid_t cid, multidevice_side_t side, uint16 audio_context, generic_source_t *source, bool is_foreground);

/*! \brief Send an LE Audio unicast voice source connect/disconnect message.

    \param id               The notification message id.
    \param voice_source     Voice source identifier.
 */
void LeAudioMessages_SendUnicastVoiceConnectStatus(MessageId id, voice_source_t voice_source);

/*! \brief Send an LE Audio unicast media streaming status message.

    \param id               The notification message id.
    \param audio_source     Audio source identifier.
    \param audio_context    Connected audio context.

 */
void LeAudioMessages_SendUnicastMediaConnectStatus(MessageId id, audio_source_t audio_source, uint16 audio_context);

/*! \brief Send an LE Audio unicast CIS connected/disconnected message.

    \param id          The notification message id.
    \param side        The multidevice side for which the CIS was connected.
    \param cis_id      Identifier for the connected CIS isochronous stream.
    \param cis_handle  Handle for the connected CIS isochronous stream.
    \param cis_dir     CIS direction.
    \param cid         The gatt connection id
 */
void LeAudioMessages_SendUnicastCisConnectStatus(MessageId id, multidevice_side_t side, uint8 cis_id, uint16 cis_handle, uint8 cis_dir, gatt_cid_t cid);

/*! \brief Send an LE Audio unicast stream active/inactive message.
    \param id                              The notification message id.
    \param tp_bdaddr                       bd address of the device which started/stopped the unicast streaming
    \param generic_source_t                Generic source which become active/inactive.
    \param audio_context                   The streaming audio context
 */
void LeAudioMessages_SendUnicastStreamStatus(MessageId id, gatt_cid_t cid, generic_source_t *source, uint16 audio_context);

/*! \brief Send an LE Audio unicast Media Update Status

    \param id                              The notification message id.
    \param audio_source_t                  Audio source which needs an update
 */
void LeAudioMessages_SendUnicastMediaUpdateStatus(MessageId id, audio_source_t audio_source);

/*! \brief Check if the message is pending for any registered client

    \param id   The message id to be checked.

    \return TRUE if the message is pending for any client, else FALSE
 */
bool LeAudioMessages_IsMessagePendingForAnyClient(MessageId id);

#endif /* INCLUDE_LE_AUDIO_UNICAST */

/*! \brief Send LE broadcast audio connected notification. */
#define LeAudioMessages_SendBroadcastAudioConnected(source) \
    LeAudioMessages_SendBroadcastConnectStatus(LE_AUDIO_BROADCAST_CONNECTED, source)

/*! \brief Send LE broadcast audio disconnected notification. */
#define LeAudioMessages_SendBroadcastAudioDisconnected(source) \
    LeAudioMessages_SendBroadcastConnectStatus(LE_AUDIO_BROADCAST_DISCONNECTED, source)

#ifdef INCLUDE_LE_AUDIO_UNICAST
/*! \brief Send LE Unicast Voice connected notification. */
#define LeAudioMessages_SendUnicastVoiceConnected(source) \
    LeAudioMessages_SendUnicastVoiceConnectStatus(LE_AUDIO_UNICAST_VOICE_CONNECTED, source)

/*! \brief Send LE Unicast Voice disconnected notification. */
#define LeAudioMessages_SendUnicastVoiceDisconnected(source) \
    LeAudioMessages_SendUnicastVoiceConnectStatus(LE_AUDIO_UNICAST_VOICE_DISCONNECTED, source)

/*! \brief Send LE Unicast media connected notification. */
#define LeAudioMessages_SendUnicastMediaConnected(source, audio_context) \
    LeAudioMessages_SendUnicastMediaConnectStatus(LE_AUDIO_UNICAST_MEDIA_CONNECTED, source, audio_context)

/*! \brief Send LE Unicast media disconnected notification. */
#define LeAudioMessages_SendUnicastMediaDisconnected(source, audio_context) \
    LeAudioMessages_SendUnicastMediaConnectStatus(LE_AUDIO_UNICAST_MEDIA_DISCONNECTED, source, audio_context)

/*! \brief Send LE unicast audio CIS connected notification. */
#define LeAudioMessages_SendUnicastAudioCisConnected(side, cis_id, cis_handle, cis_dir, cid) \
    LeAudioMessages_SendUnicastCisConnectStatus(LE_AUDIO_UNICAST_CIS_CONNECTED, side, cis_id, cis_handle, cis_dir, cid)

/*! \brief Send LE unicast audio CIS disconnected notification. */
#define LeAudioMessages_SendUnicastAudioCisDisconnected(side, cis_id, cis_handle, cid) \
    LeAudioMessages_SendUnicastCisConnectStatus(LE_AUDIO_UNICAST_CIS_DISCONNECTED, side, cis_id, cis_handle, 0, cid)

/*! \brief Send LE unicast audio disabled notification. */
#define LeAudioMessages_SendUnicastDisabled(handset_device, source, audio_context) \
        LeAudioMessages_SendUnicastStreamStatus(LE_AUDIO_UNICAST_DISABLED_IND, handset_device, source, audio_context)

/*! \brief Send LE unicast audio metadata update notification. */
#define LeAudioMessages_SendMetadataUpdateInd(handset_device, source, audio_context) \
    LeAudioMessages_SendUnicastStreamStatus(LE_AUDIO_UNICAST_UPDATE_METADATA_IND, handset_device, source, audio_context)

/*! \brief Send LE unicast media data path ready notification. */
#define LeAudioMessages_SendUnicastMediaDataPathReady(source, audio_context) \
    LeAudioMessages_SendUnicastMediaConnectStatus(LE_AUDIO_UNICAST_MEDIA_DATA_PATH_READY, source, audio_context)

/*! \brief Send LE Unicast media updated notification. */
#define LeAudioMessages_SendUnicastMediaUpdated(source) \
    LeAudioMessages_SendUnicastMediaUpdateStatus(LE_AUDIO_UNICAST_MEDIA_UPDATE_IND, source)

#endif /* INCLUDE_LE_AUDIO_UNICAST */

/*! @} */

#endif /* LE_AUDIO_MESSAGES_H_ */
